package com.getword.service.impl;

import com.getword.domain.*;
import com.getword.mongodao.*;
import com.getword.service.VideoService;
import com.getword.utils.PathUtil;
import com.getword.utils.SpringContextUtil;
import com.getword.web.controller.ApiVideoController;
import com.getword.web.model.Result;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.result.UpdateResult;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.bson.types.ObjectId;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.List;


@Service
//@Transactional
public class VideoServiceImpl implements VideoService {
    @Autowired
    private OutlineDetailRepository outlineDetailRepository;
    @Autowired
    private VideoRepository videoRepository;
    @Autowired
    private OutlineRepository outlineRepository;
    @Autowired
    private GradeRepository gradeRepository;
    @Autowired
    private CourseRepository courseRepository;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private GridFsTemplate gridFsTemplate;
    @Autowired
    private GridFSBucket gridFSBucket;
    @Autowired
    private VideoZanRepository videoZanRepository;

    // 将字幕文件保存到数据库
    @Override
    public Result uploadCaption(MultipartFile file, HttpServletRequest request) {
        // 是否上传了视频文件
        Video video = (Video) request.getSession().getAttribute(ApiVideoController.VIDEO);

        if (video == null || StringUtils.isBlank(video.getVideoFilename())) {
            // 如果没上传视频，需要先上传视频
            return Result.fail("请先上传视频");
        }
        // 获取上传字幕文件的后缀名
        String ext = PathUtil.getFileExt(file.getOriginalFilename());
        // 如果字幕文件是srt文件，则需要将srt转成vtt
        try {
            String filename = video.getVideoFilename().substring(0, video.getVideoFilename().lastIndexOf(".")) + "." + ext;
            video.setCaptionExt(ext);
            video.setCaptionOriginalName(file.getOriginalFilename());
            video.setCaptionFilename(filename);
            File captionFile = new File(ResourceUtils.getURL("classpath:static").getPath() + "/upload/video/" + filename);
            file.transferTo(captionFile);
            request.getSession().setAttribute(ApiVideoController.VIDEO, video);
            // 保存到数据库
            String s = IOUtils.toString(file.getInputStream(), StandardCharsets.UTF_8);
            video.setCaptionText(s);
            return Result.success(new HashMap<String, Object>() {{
                put("filename", filename);
                put("orgFilename", file.getOriginalFilename());
            }});
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail("服务器异常");
        }
    }

    @Override
    public Result uploadCover(MultipartFile file, HttpServletRequest request) {
        // 是否上传了视频文件
        Video video = (Video) request.getSession().getAttribute(ApiVideoController.VIDEO);

        if (video == null || StringUtils.isBlank(video.getVideoFilename())) {
            // 如果没上传视频，需要先上传视频
            return Result.fail("请先上传视频");
        }
        // 获取上传字幕文件的后缀名
        String ext = PathUtil.getFileExt(file.getOriginalFilename());
        // 如果字幕文件是srt文件，则需要将srt转成vtt
        try {
            String filename = video.getVideoFilename().substring(0, video.getVideoFilename().lastIndexOf(".")) + "." + ext;
            video.setCoverImg("/upload/video/images/"+filename);
            File coverFile = new File(ResourceUtils.getURL("classpath:static").getPath() + "/upload/video/images/" + filename);
            file.transferTo(coverFile);
            request.getSession().setAttribute(ApiVideoController.VIDEO, video);
            return Result.success(new HashMap<String, Object>() {{
                put("filename", filename);
                put("orgFilename", file.getOriginalFilename());
            }});
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail("服务器异常");
        }
    }

    @Override
    public Result saveVideo(Video video, Long outlineId, String detailNum) {
        // 查询outline
        Outline outline = outlineRepository.findOutlineById(outlineId);
        video.setCourse(outline.getCourse());
        video.setGrade(outline.getCourse().getGrade());
        OutlineDetail outlineDetail = outlineDetailRepository.findOutlineDetailByOutlineIdAndNum(outlineId, detailNum);
        video.setOutlineDetail(outlineDetail);
        // user
        User user = new User(SpringContextUtil.getLoginUser().getId());
        video.setUser(user);
        Video save = videoRepository.save(video);
        if(save != null){
            return Result.success(save);
        }
        return Result.fail("保存失败");
    }

    @Override
//    @Cacheable
    public Result getVideos(Pageable page, Long gradeId, Long courseId) {
        Video video = new Video();
        if(gradeId!=null&&gradeId!=0){
            video.setGrade(gradeRepository.findGradeById(gradeId));
        }
        if(courseId!=null&&courseId!=0){
            video.setCourse(courseRepository.findCourseById(courseId));
        }
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式：模糊查询
                .withIgnoreCase(true); //采用“包含匹配”的方式查询
        Example<Video> example = Example.of(video, matcher);
        BasicDBObject fieldsObject = new BasicDBObject();
        fieldsObject.put("title", 1);
        fieldsObject.put("coverImg", 1);
        fieldsObject.put("course", 1);
        Page<Video> result = videoRepository.findAllPage(example, fieldsObject, page);
        return Result.success(result);

    }
    @Override
    public Page<Video> getVideoPage(Pageable page, Long gradeId, Long courseId, String title, User user) {
        Video video = new Video();
        if(gradeId!=null&&gradeId!=0){
            video.setGrade(gradeRepository.findGradeById(gradeId));
        }
        if(courseId!=null&&courseId!=0){
            video.setCourse(courseRepository.findCourseById(courseId));
        }
        video.setTitle(title);
        video.setUser(user);
        ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING) //改变默认字符串匹配方式：模糊查询
                .withIgnoreCase(true)
                .withMatcher("title", ExampleMatcher.GenericPropertyMatchers.contains());; //采用“包含匹配”的方式查询
        Example<Video> example = Example.of(video, matcher);
        BasicDBObject fieldsObject = new BasicDBObject();
        fieldsObject.put("title", 1);
        fieldsObject.put("coverImg", 1);
        fieldsObject.put("outlineDetail", 1);
        fieldsObject.put("negGrade", 1);
        fieldsObject.put("posGrade", 1);
        fieldsObject.put("uploadTime", 1);
        fieldsObject.put("course", 1);
        Page<Video> all = videoRepository.findAllPage(example, fieldsObject, page);
        return all;
    }

    @Override
    public Result getVideoById(String id) {
        Video video = videoRepository.findVideoById(id);
        if(video == null){
            return Result.fail("视频不存在");
        }
        return Result.success(video);
    }

    @Override
    public Result addSentiment(Video video) {
        // 更新timelines，keywords字段
        Query query = Query.query(Criteria.where("id").is(video.getId()));
        Update update = new Update();
        update.set("keywords",video.getKeywords());
        update.set("timelines", video.getTimelines());
        UpdateResult result = mongoTemplate.updateFirst(query, update, Video.class);
        if(result.getModifiedCount()>0){
            return Result.success(result);
        }else{
            return Result.fail("failed");
        }
    }

    @Override
    public Result zan(String videoId) {
        User user = SpringContextUtil.getLoginUser();
        if (StringUtils.isBlank(videoId)) {
            return Result.fail("参数不合法");
        }
        // 是否已经点赞了
        VideoZan zaned = videoZanRepository.findVideoZanByUserIdAndVideoId(user.getId(), videoId);
        if(zaned !=null){
            return Result.fail("该视频已经点赞了");
        }
        VideoZan zan = new VideoZan();
        zan.setUserId(user.getId());
        zan.setVideoId(videoId);
        zan.setDate(new Date());
        VideoZan save = videoZanRepository.save(zan);
        return Result.success(save);
    }

    @Override
    public Result getZanState(String videoId) {
        User user = SpringContextUtil.getLoginUser();
        if (StringUtils.isBlank(videoId)) {
            return Result.fail("参数不合法");
        }
        // 是否已经点赞了
        VideoZan zaned = videoZanRepository.findVideoZanByUserIdAndVideoId(user.getId(), videoId);
        if(zaned !=null){
            return Result.success(true);
        }
        return Result.success(false);
    }

    @Override
    public Result getZanCount(String videoId) {
        long count = mongoTemplate.count(Query.query(Criteria.where("videoId").is(videoId)), VideoZan.class);
        return Result.success(count);
    }


}
